/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package webserver;

/**
 * This class represents a worker Thread in the ThreadPool
 * Tasks can be assigned to this worker and will be performed by him
 * 
 */
public class ThreadPoolWorker extends Thread {

	// Variables
	private final ThreadPool pool;
	private volatile Runnable work;
	private boolean idle;
	private volatile boolean finish;

	/**
	 * ThreadPoolWorker Overloaded Constructor
	 * @param pool - The ThreadPool which created and manages this Worker
	 */
	public ThreadPoolWorker(ThreadPool pool) {
		// Initialize
		this.pool = pool;
		this.idle = true;
		this.finish = false;
		this.work = null;
		this.setDaemon(true);
		this.start();
	}

	/**
	 * Check whether the Worker is idle or not
	 * @return boolean - The idle state of this Worker
	 */
	public synchronized boolean isIdle() {
		return this.idle;
	}

	/**
	 * Set the current Workload for this Worker to the given Runnable
	 * @param r - The Runnable which should be "done" by this Worker
	 * @throws IllegalStateException
	 */
	public synchronized void setWork(Runnable r) throws IllegalStateException {
		// Check if worker is really idle
		if (!this.idle && r != null) {
			throw new IllegalStateException("This worker is not IDLE!");
		} else {
			this.work = r;
		}

		// Set idle state
		if (this.work != null) {
			this.idle = false;
		} else {
			this.idle = true;
		}
	}

	/**
	 * The run Method is automatically called when the start() function is called for the Worker
	 */
	@Override
	public void run() {

		// Do until I should finish
		while (!this.finish) {
			// Check for new work to Do
			if (this.work != null) {

				// Try to do the work
				try {
					this.work.run();
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					this.setWork(null);
				}
			}

			// Wait for new Work to do..
			this.setWork(this.pool.getNewWork());
		}
	}

	/**
	 * Tell the Worker to finish ASAP
	 */
	public void finish() {
		this.finish = true;

		try {
			this.interrupt();
		} catch (SecurityException se) {
			// ignore :)
		}

		this.pool.workerFinished(this);
	}
}
